﻿namespace PokerSimulator
{
	using System;
	using System.Collections.Generic;
	using System.Globalization;
	using System.Threading.Tasks;

	using PugLib.Extensions.Collections;

	public class TexasHoldEmGame : Game
	{
		public TexasHoldEmGame()
		{
			MaxPlayerCount = 22;
			PlayerCount = 2;
			StartingCardsInHand = 2;
			MaxCardsInHandCount = 7;
			SharedCardsCount = 5;
			GamesToPlay = 1;
			MakeHands();
		}

		public TexasHoldEmGame(int playerCount)
		{
			MaxPlayerCount = 22;
			if (playerCount > MaxPlayerCount)
			{
				throw new ArgumentException(string.Format(CultureInfo.InvariantCulture, "{0} players exceeds maximum of {1}", playerCount, MaxPlayerCount));
			}
			PlayerCount = playerCount;
			StartingCardsInHand = 2;
			MaxCardsInHandCount = 7;
			SharedCardsCount = 5;
			GamesToPlay = 1;
			MakeHands();
		}

		protected override void Deal()
		{
			// preflop deal           
			DealCardToEachPlayer();
			DealCardToEachPlayer();

			// check if anyone wants to fold preflop
			CheckForPreFlopFolds();

			// shared deal from this point on
			// deal flop 
			BurnTopCard();
			DealSharedCardToEachPlayer();
			DealSharedCardToEachPlayer();
			DealSharedCardToEachPlayer();

			// deal turn           
			BurnTopCard();
			DealSharedCardToEachPlayer();
			// deal river
			BurnTopCard();
			DealSharedCardToEachPlayer();

			GetHandValues(Hands);

			if (VerboseLogging)
			{
				PrintSummary();
			}
		}

		private static void GetHandValues(IEnumerable<Hand> hands)
		{
			Parallel.ForEach(hands, h =>
			{
				if (h.StillPlaying)
				{
					h.UpdateValue(GameType.TexasHoldEm);
				}
			});
		}

		private void DealSharedCardToEachPlayer()
		{
			Card card = Deck.DealCard();
			SharedHand.AddCard(card);
			// add shared card to each person's hand
			Hands.ForEach(h =>
			{
				if (h.StillPlaying)
				{
					h.AddCard(card);
				}
			});
		}

		private void CheckForPreFlopFolds()
		{
			Parallel.ForEach(Hands, h => h.FoldPreFlop());
		}

		private void DealCardToEachPlayer()
		{
			Hands.ForEach(h => h.AddCard(Deck.DealCard()));
		}

		private void BurnTopCard()
		{
			Deck.DealCard();
		}
	}
}